//
//  JPConfig.m
//  MicroTransfer
//
//  Created by jacksonpan on 13-1-21.
//  Copyright (c) 2013年 weichuan. All rights reserved.
//

#import "JPConfig.h"
#import "FMDatabase.h"

#define JPConfig_DATABASE_NAME                      @"JPConfig.db"
#define JPConfig_V2_TABLE_NAME                      @"jpconfig"

#define JPConfig_VALUE_TYPE_INT                     @"int"
#define JPConfig_VALUE_TYPE_BOOL                    @"bool"
#define JPConfig_VALUE_TYPE_FLOAT                   @"float"
#define JPConfig_VALUE_TYPE_STRING                  @"string"
#define JPConfig_VALUE_TYPE_LONG                    @"long"

typedef enum _ENUM_JPConfig_TYPE
{
    ENUM_JPConfig_TYPE_NONE = 0,
    ENUM_JPConfig_TYPE_INT = 2,
    ENUM_JPConfig_TYPE_BOOL = 3,
    ENUM_JPConfig_TYPE_FLOAT = 4,
    ENUM_JPConfig_TYPE_STRING = 5,
    ENUM_JPConfig_TYPE_LONG = 6,
}ENUM_JPConfig_TYPE;

@interface JPConfig ()
{
    __strong FMDatabase* dbPointer;
    __strong NSDictionary* defaultValue;
}

@property(nonatomic,retain)NSRecursiveLock *lock;

@end

@implementation JPConfig
DEF_SINGLETON(JPConfig)

-(NSRecursiveLock *)lock{
    if (!_lock) {
        _lock = [[NSRecursiveLock alloc] init];
    }
    return _lock;
}

- (void)initForDB
{
    [self.lock lock];
    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSArray* rs = [JPConfig_DATABASE_NAME componentsSeparatedByString:@"."];
    NSString *realPath = [documentPath stringByAppendingPathComponent:JPConfig_DATABASE_NAME];
    
    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:[rs objectAtIndex:0] ofType:[rs objectAtIndex:1]];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:realPath]){
        NSError *error;
        if (![fileManager copyItemAtPath:sourcePath toPath:realPath error:&error]) {
            NSLog(@"%@",[error localizedDescription]);
        }
    }
    
    ZTLog(@"复制sqlite到路径：%@成功。",realPath);
    
    dbPointer = [FMDatabase databaseWithPath:realPath];
    [self.lock unlock];
}

- (void)open
{
    [dbPointer open];
}

- (void)close
{
    [dbPointer close];
}

- (id)init
{
    self = [super init];
    if(self)
    {
        [self initForDB];
    }
    return self;
}

- (void)clear
{
    [self open];
    [dbPointer executeUpdate:[NSString stringWithFormat:@"DELETE FROM %@", JPConfig_V2_TABLE_NAME]];
    [self close];
}

- (void)cpDBToDesktop
{
    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *realPath = [documentPath stringByAppendingPathComponent:JPConfig_DATABASE_NAME];
    NSFileManager* fm = [NSFileManager defaultManager];
    NSError* er = nil;
    NSString* dst = [NSString stringWithFormat:@"/Users/jacksonpan/Desktop/%@", JPConfig_DATABASE_NAME];
    if([fm fileExistsAtPath:dst])
    {
        [fm removeItemAtPath:dst error:&er];
        if(er)
        {
            NSLog(@"err:%@", er);
        }
    }
    [fm copyItemAtPath:realPath toPath:dst error:&er];
}

- (BOOL)existObjectForKey:(NSString*)defaultName
{
    return [self objectForKey:defaultName]?YES:NO;
}

- (id)objectForKey:(NSString *)defaultName
{
    [self.lock lock];
    [self open];
    id object = nil;
    NSString* sql = [NSString stringWithFormat:@"select * from %@ where key = '%@'", JPConfig_V2_TABLE_NAME, defaultName];
    //DDLogInfo(@"%@",sql);
    FMResultSet* rs = [dbPointer executeQuery:sql];
    while ([rs next])
    {
        NSString* type = [rs objectForColumnIndex:1];
        object = [rs objectForColumnName:[NSString stringWithFormat:@"value_%@", type]];
    }
    [rs close];
    [self close];
    [self.lock unlock];
    return object;
}

//单存多取
- (NSMutableArray *)objectForKeyReturnArray:(NSString *)defaultName
{
    [self.lock lock];
    [self open];
    NSMutableArray *object = [[NSMutableArray alloc]init];
    NSString* sql = [NSString stringWithFormat:@"select * from %@ where key = '%@'", JPConfig_V2_TABLE_NAME, defaultName];
    NSLog(@"%@",sql);
    FMResultSet* rs = [dbPointer executeQuery:sql];
    while ([rs next])
    {
//        NSString* type = [rs objectForColumnIndex:1];
        [object addObject:[rs objectForColumnName:[NSString stringWithFormat:@"value_%@",@"string" ]]];
    }
    [rs close];
    [self close];
    [self.lock unlock];
    return object;
}

- (NSString*)getTypeStringWithType:(ENUM_JPConfig_TYPE)type
{
    NSString* ret = nil;
    switch (type) {
        case ENUM_JPConfig_TYPE_INT:
            ret = JPConfig_VALUE_TYPE_INT;
            break;
        case ENUM_JPConfig_TYPE_BOOL:
            ret = JPConfig_VALUE_TYPE_BOOL;
            break;
        case ENUM_JPConfig_TYPE_FLOAT:
            ret = JPConfig_VALUE_TYPE_FLOAT;
            break;
        case ENUM_JPConfig_TYPE_STRING:
            ret = JPConfig_VALUE_TYPE_STRING;
            break;
        case ENUM_JPConfig_TYPE_LONG:
            ret = JPConfig_VALUE_TYPE_LONG;
            break;
        default:
            break;
    }
    return ret;
}

- (NSString*)objectTypeWithTypeString:(NSString*)typeString{
    if(typeString == nil) return nil;
    return [NSString stringWithFormat:@"value_%@", typeString];
}

- (void)setObject:(id)value forKey:(NSString *)defaultName{
    [self.lock lock];
    ENUM_JPConfig_TYPE type = ENUM_JPConfig_TYPE_NONE;
    if(value == nil) value = [NSNull null];
    if([value isKindOfClass:[NSNumber class]])
    {
        const char* t = [value objCType];
        NSString* tt = [NSString stringWithCString:t encoding:NSUTF8StringEncoding];
        //NSLog(@"%@", tt);
        if([tt isEqualToString:@"c"]){
            type = ENUM_JPConfig_TYPE_BOOL;
        }else if([tt isEqualToString:@"f"]){
            type = ENUM_JPConfig_TYPE_FLOAT;
        }else if([tt isEqualToString:@"i"]){
            type = ENUM_JPConfig_TYPE_INT;
        }else if([tt isEqualToString:@"q"]){
            type = ENUM_JPConfig_TYPE_LONG;
        }
    }else if([value isKindOfClass:[NSString class]]){
        type = ENUM_JPConfig_TYPE_STRING;
    }else if([value isKindOfClass:[NSNull class]]){
        type = ENUM_JPConfig_TYPE_STRING;
    }
    
    NSString* sql = nil;
    if([self existObjectForKey:defaultName]){
        sql = [NSString stringWithFormat:@"update %@ set %@ = ? WHERE key = '%@'", JPConfig_V2_TABLE_NAME, [self objectTypeWithTypeString:[self getTypeStringWithType:type]], defaultName];
    }else{
        sql = [NSString stringWithFormat:@"insert into %@ (key, objectType, %@) VALUES ('%@','%@',?)", JPConfig_V2_TABLE_NAME, [self objectTypeWithTypeString:[self getTypeStringWithType:type]], defaultName, [self getTypeStringWithType:type]];
    }
    [self open];
    [dbPointer executeUpdate:sql, value];
    [self close];
    [self.lock unlock];
}

- (void)removeObjectForKey:(NSString *)defaultName{
    [self.lock lock];
    NSString* sql = [NSString stringWithFormat:@"delete from %@ where key = '%@'", JPConfig_V2_TABLE_NAME, defaultName];
    [self open];
    /*BOOL ret = */[dbPointer executeUpdate:sql];
    [self close];
    [self.lock unlock];
}

- (NSString *)stringForKey:(NSString *)defaultName{
    [self.lock lock];
    id object = [self objectForKey:defaultName];
    [self.lock unlock];
    return object;
}

- (NSInteger)integerForKey:(NSString *)defaultName{
    [self.lock lock];
    id object = [self objectForKey:defaultName];
    [self.lock unlock];
    return [object intValue];
}

- (int)intForKey:(NSString *)defaultName{
    [self.lock lock];
    int i = (int)[self integerForKey:defaultName];
    [self.lock unlock];
    return i;
}

- (float)floatForKey:(NSString *)defaultName{
    [self.lock lock];
    id object = [self objectForKey:defaultName];
    [self.lock unlock];
    return [object doubleValue];
}

- (BOOL)boolForKey:(NSString *)defaultName{
    id object = [self objectForKey:defaultName];
    if(object == nil) return NO;
    return [object intValue];
}

- (void)setString:(NSString*)value forKey:(NSString *)defaultName{
    [self.lock lock];
    [self setObject:value forKey:defaultName];
    [self.lock unlock];
}

- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName{
    [self.lock lock];
    [self setObject:[NSNumber numberWithInteger:value] forKey:defaultName];
    [self.lock unlock];
}

- (void)setInt:(int)value forKey:(NSString *)defaultName{
    [self.lock lock];
    [self setInteger:value forKey:defaultName];
    [self.lock unlock];
}

- (void)setFloat:(float)value forKey:(NSString *)defaultName{
    [self.lock lock];
    [self setObject:[NSNumber numberWithFloat:value] forKey:defaultName];
    [self.lock unlock];
}

- (void)setBool:(BOOL)value forKey:(NSString *)defaultName{
    [self.lock lock];
    [self setObject:[NSNumber numberWithBool:value] forKey:defaultName];
    [self.lock unlock];
}

@end
